package bll

import (
	"context"
	"manager/errors"
	"manager/store/postgres"
	"manager/utils"
	"time"

	"manager/event"
	"manager/model"
	"manager/model/entity"
	"manager/store"
)

type storeServer struct {
	iStore store.IStore
}

var StoreServer = &storeServer{}

func (a *storeServer) init() func() {
	a.iStore = postgres.Store
	return func() {}
}

func (a *storeServer) onEvent(*event.Data) {}

func (a *storeServer) Create(ctx context.Context, in *model.StoreCreateRequest) error {
	var (
		err error
	)

	c := buildStore(in)
	_, err = a.iStore.Create(ctx, c)
	return err
}

func (a *storeServer) Update(ctx context.Context, in *model.StoreUpdateRequest) error {
	var (
		dict = make(map[string]interface{})
	)

	if in.Name != nil {
		dict["name"] = *in.Name
	}

	if in.Addr != nil {
		dict["addr"] = *in.Addr
	}

	if in.Phone != nil {
		dict["phone"] = *in.Phone
	}

	if in.Coordinate != nil {
		dict["coordinate"] = *in.Coordinate
	}

	if in.ManagerID != nil {
		dict["manager_id"] = *in.ManagerID
	}

	if in.Images != nil {
		dict["images"] = *in.Images
	}

	if in.Status != nil {
		dict["status"] = *in.Status
	}

	if in.AreaID != nil {
		dict["area_id"] = *in.AreaID
	}

	if in.ZoneCode != nil {
		dict["zone_code"] = *in.ZoneCode
	}

	if in.CityCode != nil {
		dict["city_code"] = *in.CityCode
	}

	if in.ProvinceCode != nil {
		dict["province_code"] = *in.ProvinceCode
	}

	if in.CountryCode != nil {
		dict["country_code"] = *in.CountryCode
	}

	// do other update here
	dict["updated_at"] = time.Now().Unix()

	return a.iStore.Update(ctx, in.ID, dict)
}

func (a *storeServer) Delete(ctx context.Context, in *model.StoreDeleteRequest) error {
	return a.iStore.Delete(ctx, in.ID)
}

func (a *storeServer) List(ctx context.Context, in *model.StoreListRequest) (*model.StoreListResponse, error) {
	var (
		err   error
		total int
		list  []*entity.Store
		out   = &model.StoreListResponse{}
	)
	in.Size, in.Index = utils.PageUtil(in.Size, in.Index)

	if total, list, err = a.iStore.List(ctx, in); err != nil {
		return nil, err
	}

	out.Total = total
	out.Data = model.StoresEntityToDto(list)

	return out, nil
}

// GetStoreListByIds 根据门店id列表获取门店列表
func (a *storeServer) GetStoreListByIds(ctx context.Context, storeIds []int64) (rets []*model.StoreInfo, storesMap map[int64]*model.StoreInfo, err error) {
	storesMap = make(map[int64]*model.StoreInfo)
	rsp, err := a.List(ctx, &model.StoreListRequest{
		Ids: storeIds,
	})
	if err != nil {
		return
	}

	rets = rsp.Data
	for i := range rets {
		storesMap[rets[i].ID] = rets[i]
	}
	return
}

func (a *storeServer) FindByID(ctx context.Context, in *model.StoreBaseRequest) (*model.StoreInfo, error) {
	var (
		err error
		out = &model.StoreInfo{}
		ety *entity.Store
	)
	if in.ID == 0 {
		return out, errors.ParameterErr.Error()
	}
	ety, err = a.iStore.Find(ctx, in.ID)
	if err != nil {
		return out, errors.New("错误") // todo 错误码待定
	}
	out = model.StoreEntityToDto(ety)
	return out, err
}

func (a *storeServer) UpdateStatus(ctx context.Context, in *model.StoreUpdateStatusRequest) error {
	var (
		err  error
		info *model.StoreInfo
	)

	info, err = a.FindByID(ctx, &model.StoreBaseRequest{ID: in.ID})
	if err != nil {
		return err // todo 错误码未处理
	}
	if info.Status == *in.Status {
		if *in.Status == int(model.StoreOnLine) {
			return err //已上线
		}
		return err // 已下线
	}

	if err = a.Update(ctx, &model.StoreUpdateRequest{
		ID:     in.ID,
		Status: in.Status,
	}); err != nil {
		return err // 错误处理
	}
	return err
}

// CountByArea 查询地区的门店数量
func (a *storeServer) CountByArea(ctx context.Context, areaIds []int64) ([]*model.CountByAreaResponse, error) {
	return a.iStore.CountByArea(ctx, areaIds)
}

func buildStore(in *model.StoreCreateRequest) *entity.Store {
	// todo: check the entity is required
	return &entity.Store{

		Name: in.Name,

		Addr: in.Addr,

		Phone: in.Phone,

		Coordinate: in.Coordinate,

		ManagerID: in.ManagerID,

		Images: in.Images,

		Status: in.Status,

		AreaID: in.AreaID,

		OfflineTime: 0,

		ZoneCode:     in.ZoneCode,
		CityCode:     in.CityCode,
		ProvinceCode: in.ProvinceCode,
		CountryCode:  in.CountryCode,

		CreatedAt: time.Now().Unix(),

		UpdatedAt: time.Now().Unix(),
	}
}
